#include <iostream>
#include <string>
#include "user.pb.h"
#include "mprpcapplication.h"

/**
 * UserService原来是一个本地服务，提供了进程内的两个本地方法：Login和GetFriendList
 * 我们的分布式网络通信框架就是让这个服务可以被同一台主机的其他进程调用，也可以被不同
 * 主机的其他进程调用
*/

// 使用在rpc服务发布端（rpc服务提供者）
class UserService : public Joy::UserServiceRpc
{
public:
    // 处理业务的方法
    bool Login(std::string name, std::string pwd)
    {
        std::cout << "do local service Login" << std::endl;
        std::cout << "name: " << name << " pwd: " << pwd << std::endl;

        return true;
    }

    bool Register(uint32_t id, std::string name, std::string pwd)
    {
        std::cout << "do local service Register" << std::endl;
        std::cout << "id: " << id << " name: " << name << " pwd: " << pwd << std::endl;
        return true;
    }

    /*
     * 重写基类UserServiceRpc的虚函数，下面的这些方法都是框架直接调用的
     * 1. caller(调用者) ===> Login(LoginRequest) ===> muduo ===> callee
     * 2. callee(提供者) ===> Login(LoginRequest) ===> 交到下面重写的这个Login方法了
    */ 
    void Login(::google::protobuf::RpcController* controller,
                       const ::Joy::LoginRequest* request,
                       ::Joy::LoginResponse* response,
                       ::google::protobuf::Closure* done)
    {
        // 框架给业务上报了请求参数LoginRequest，应用获取相应的数据做本地业务
        std::string name = request->name();
        std::string pwd = request->pwd();

        // 做本地业务
        bool ret = Login(name, pwd); 

        // 把响应写入 包括错误码、错误消息、返回值
        Joy::ResultCode* code = response->mutable_result();
        code->set_errcode(0);
        code->set_errmsg("");
        response->set_success(ret);

        // 执行回调操作 执行响应对象数据的序列化和网络发送，这些都是由框架完成的
        done->Run();
    }

    void Register(::google::protobuf::RpcController* controller,
                       const ::Joy::RegisterRequest* request,
                       ::Joy::RegisterResponse* response,
                       ::google::protobuf::Closure* done)
    {
        uint32_t id = request->id();
        std::string name = request->name();
        std::string pwd = request->pwd();

        bool ret = Register(id, name, pwd);

        Joy::ResultCode* code = response->mutable_result();
        code->set_errcode(0);
        code->set_errmsg("");
        response->set_success(ret);

        done->Run();
    }
};

int main(int argc, char** argv)
{
    // 调用框架的初始化操作 provider -i config.conf
    MprpcApplication::Init(argc, argv);

    // provider是一个rpc网络服务对象，把UserServcie对象发布到rpc节点上
    RpcProvider provider; 
    provider.NotifyService(new UserService());

    // 启动一个rpc服务发布节点，Run以后，进程进入阻塞状态，等待远程的rpc调用请求
    provider.Run();

    return 0;
}